/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.scalia.meteocal.gui;

import com.scalia.meteocal.control.EventManager;
import com.scalia.meteocal.control.InvitationManager;
import com.scalia.meteocal.control.PlaceManager;
import com.scalia.meteocal.control.UserManager;
import com.scalia.meteocal.entity.Event;
import com.scalia.meteocal.entity.Invitation;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
/**
 *
 * @author gabriele
 */
@ManagedBean
@ViewScoped
public class EventBean implements Serializable {
    @EJB
    UserManager userManager;
    
    @EJB
    EventManager eventManager;
    
    @EJB
    PlaceManager placeManager;
    
    @EJB
    InvitationManager invitationManager;
    

    private Event event;
    
    private static final String NOT_ENABLED = "Not enabled";
    private String[] selectedWeatherTypes;
    private List<Invitation> currentInvitations;
    private String[] newInvitations;  
    private Invitation invitation; //Useful if user is invited only
    private boolean eventExists;

    @PostConstruct
    public void init() {
        try {
            event = eventManager.getEvent(Long.parseLong(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id")));
        } catch(Exception e) {
            eventExists = false;
            return;
        }
        if (event == null) {
            eventExists = false;
            return;
        } else if (event.isDeleted()) {
            return;
        }
        eventExists = true;
        selectedWeatherTypes = eventManager.badWeatherTypesDecoder(event.getBadWeatherTypes());
        currentInvitations = invitationManager.getInvitationsOfEvent(event);

        invitation = invitationManager.getInvitationOf(userManager.getLoggedUser(), event);
    }
    
    public String getPageTitle() {
        return "Event: " + event.getName();
    }

    public Event getEvent() {
        return event;
    }

    public void setEvent(Event event) {
        this.event = event;
    }
    
    public Map<String, String> getCities() {
        return placeManager.getCities(event.getCountry());
    }
    
    public List<String> getTemperatures() {
        ArrayList<String> defaultTemperatures = new ArrayList<>();
        for (int i = Event.MIN_TEMPERATURE_AVAIABLE; i < Event.MAX_TEMPERATURE_AVAIABLE; i++) {
            defaultTemperatures.add(String.valueOf((float) i));
            if (i+0.5 < Event.MAX_TEMPERATURE_AVAIABLE)
                defaultTemperatures.add(String.valueOf((float) ((float) i + 0.5)));
        }
        return defaultTemperatures;
    }
    
    public void setMinTemperature(String minTemperature) {
        if (minTemperature.equals(NOT_ENABLED)) {
            event.setMinTemperature(null);      
        } else {
            event.setMinTemperature(Float.parseFloat(minTemperature));
        }
    }

    public String getMinTemperature() {
        return event.getMinTemperature() == null ? NOT_ENABLED : String.valueOf(event.getMinTemperature());
    }
    
    public void setMaxTemperature(String maxTemperature) {
        if (maxTemperature.equals(NOT_ENABLED)) {
            event.setMaxTemperature(null);      
        } else {
            event.setMaxTemperature(Float.parseFloat(maxTemperature));
        }
    }

    public String getMaxTemperature() {
        return event.getMaxTemperature() == null ? NOT_ENABLED : String.valueOf(event.getMaxTemperature());
    }

    public String[] getSelectedWeatherTypes() {
        return selectedWeatherTypes;
    }

    public void setSelectedWeatherTypes(String[] selectedWeatherTypes) {
        this.selectedWeatherTypes = selectedWeatherTypes;
        event.setBadWeatherTypes(eventManager.badWeatherTypesEncoder(selectedWeatherTypes));
    }
   
    public String getBadWeathersWellFormatted() {
        if (selectedWeatherTypes.length == 0) 
            return "None";
        String result = new String();
        for (String s: selectedWeatherTypes) 
            result = result.concat(s).concat(", ");
        result = result.isEmpty() ? "None" : result.substring(0, result.length() - 2);
        return result;
    }
    
    public void saveChanges() {
        if (event.isNotificated()) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "The event can not be modified less than 24 hours before", "The event can not be modified less than 24 hours before"));
            return;
        }
        eventManager.modifyEvent(event);
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "The event has been saved", "The event has been saved"));
    }
        
    public String delete() {
        eventManager.deleteEvent(event);
        return "/user/userpage?faces-redirect=true";
    }

    public List<Invitation> getCurrentInvitations() {
        return currentInvitations;
    }
    
    public String getCurrentPartecipantsNumber() {
        int i = 1; //the creator is always a partecipant
        for (Invitation inv : currentInvitations) {
            if (inv.isAccepted()) 
                i++;
        }
        return String.valueOf(i);   
    }   

    public String[] getNewInvitations() {
        return newInvitations;
    }

    public void setNewInvitations(String[] newInvitations) {
        this.newInvitations = newInvitations;
    }

    public List<String> getNewPossibleInvitations() {
        List<String> currentInvitationsUserNames = new ArrayList<>();
        for (Invitation invitation : currentInvitations) {
            currentInvitationsUserNames.add(invitation.getUser().getUsername());
        }
        return invitationManager.getNewPossibleInvitationsUsernames(currentInvitationsUserNames);
    }
    
    public void addNewInvitations() {
        invitationManager.sendInvitationsTo(newInvitations, event);
        newInvitations = null;
        currentInvitations = invitationManager.getInvitationsOfEvent(event);
    }
    
    public boolean getIsCreator() {
        return event.getCreator().getUsername().equals(userManager.getLoggedUser().getUsername());
    }
    
    public boolean isInvited() {
        return invitation!=null;
    }
    
    public Invitation getInvitation() {
        return invitation;
    }
    
    public void setInvitation(Invitation invitation) {
        this.invitation = invitation;
    }
    
    public String getOutdoorWellFormatted() {
        return event.isOutdoor() ? "Yes" : "No";
    }
    
    public void changeInvitation() {
        invitationManager.changeInvitation(invitation);       
        currentInvitations = invitationManager.getInvitationsOfEvent(event);
    }
    
    public String getWeatherForecast() {
        if (event.getWeatherTypeForecast() == null) {
            return "A weather forecast is not avaiable for this event yet.";
        }
        return event.getWeatherTypeForecast() + " with an average temperature of " + String.valueOf(event.getForecastTemperature()) + " °C.";
    }
    
        
    public void validateEndDate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (event==null || event.getStartTime() == null)
            return;
        
        Date endDate = (Date)value;
        
        if (endDate.before(event.getStartTime()))
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "The end date must be after the start date", "The end date must be after the start date"));
    }
    
    public void validateMaximumTemperature(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (value == null) 
            return;
        
        setMaxTemperature((String)value);
        
        if (event.getMinTemperature() == null || event.getMaxTemperature() == null) {
            return;
        }
        if (event.getMinTemperature() >  event.getMaxTemperature()) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "The maximum temperature must be greater than the minimum one", "The maximum temperature must be greater than the minimum one"));
        }
    }
    
    public boolean getEventExists() {
        return eventExists;
    }
    
    public void confirmDelete() {
        FacesContext context = FacesContext.getCurrentInstance();
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Successful", "The event has been deleted");
        context.getExternalContext().getFlash().setKeepMessages(true);
        context.addMessage(null, message);
    }
  
}
